home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 2924.ZIP / DMLXREF.ARC / GEN.IMP < prev    next >
Encoding:
Text File  |  1988-12-22  |  24.2 KB  |  875 lines

  1.  
  2.  
  3. (**************************************************************************)
  4. (*                                                                        *)
  5. (*          1)   System programming extensions                            *)
  6. (*                                                                        *)
  7. (*                                                                        *)
  8. (**************************************************************************)
  9.  
  10. PROCEDURE Abend(ExitCode : BYTE;
  11.                 ProcAddr : POINTER);
  12.  
  13. VAR
  14.   CallerOfs : WORD;
  15.   CallerSeg : WORD;
  16.  
  17. CONST
  18.   Hex : ARRAY[0..15] OF CHAR = '0123456789ABCDEF';
  19.  
  20.   FUNCTION W2H(Num : WORD) : STRING;
  21.   BEGIN
  22.     W2H := Hex[HI(Num) SHR 4] + Hex[HI(Num) AND $0F] +
  23.            Hex[LO(Num) SHR 4] + Hex[LO(Num) AND $0F];
  24.   END;
  25.  
  26. BEGIN
  27.   IF ProcAddr <> NIL THEN BEGIN
  28.     CallerOfs := OFS(ProcAddr^);
  29.     CallerSeg := SEG(ProcAddr^)-PrefixSeg-16;
  30.     END
  31.   ELSE BEGIN
  32.     INLINE($8B/$46/$02);            { MOV AX,[BP+2] }
  33.     INLINE($36/$89/$46/<CallerOfs); { MOV SS:[BP-OFS(CallerOfs)],AX }
  34.     INLINE($8B/$46/$04);            { MOV AX,[BP+4] }
  35.     INLINE($36/$89/$46/<CallerSeg); { MOV SS:[BP-OFS(CallerSeg)],AX }
  36.     CallerSeg := CallerSeg-PrefixSeg-16;
  37.     CallerOfs := CallerOfs - 4;
  38.     END;
  39.   TEXTMODE(LastMode);
  40.   WRITELN(^G^J^M,'User Abend Number: ',ExitCode,' Addr: ',W2H(CallerSeg),':',W2H(CallerOfs));
  41.   HALT(ExitCode);
  42. END;
  43.  
  44. VAR
  45.   ProcAddr_G : POINTER;
  46.  
  47. PROCEDURE CallProc;
  48.   INLINE($FF/$1E/ProcAddr_G);   { CALL FAR [ProcAddr_G] -> An indirect FAR Call }
  49.  
  50. PROCEDURE CallProcedure(ProcAddr : POINTER);
  51. BEGIN
  52.   ProcAddr_G := ProcAddr;
  53.   CallProc;
  54. END;
  55.  
  56. PROCEDURE CallProcX(I1 : INTEGER; VAR S1 : STRING; VAR I2 : INTEGER);
  57.   INLINE($FF/$1E/ProcAddr_G);   { CALL FAR [ProcAddr_G] -> An indirect FAR Call }
  58.  
  59. PROCEDURE CallProcedureX(ProcAddr : POINTER; I1 : INTEGER; VAR S1 : STRING; VAR I2 : INTEGER);
  60. BEGIN
  61.   ProcAddr_G := ProcAddr;
  62.   CallProcX(I1,S1,I2);
  63. END;
  64.  
  65. FUNCTION LongAddr(Seg, Ofs : WORD) : LONGINT;
  66.  
  67. BEGIN
  68.   LongAddr := LONGINT(Seg) * 16 + Ofs;
  69. END;
  70.  
  71. FUNCTION Same (VAR Var1, Var2; Len : WORD) : BOOLEAN;
  72. VAR
  73.   Ptr1,
  74.   Ptr2 : ^BYTE;
  75.   Ctr  : INTEGER;
  76.   Test : BOOLEAN;
  77.  
  78. BEGIN
  79.   Len  := PRED(Len); {Since our counter starts from zero, and Len starts at one}
  80.   Ptr1 := ADDR(Var1);
  81.   Ptr2 := ADDR(Var2);
  82.  
  83.   Ctr := 0;
  84.   REPEAT
  85.     Test := (Ptr1^ = Ptr2^);
  86.     Ctr := SUCC(Ctr);
  87.     Ptr1 := PTR(SEG(Ptr1^),SUCC(OFS(Ptr1^)));
  88.     Ptr2 := PTR(SEG(Ptr2^),SUCC(OFS(Ptr2^)));
  89.     UNTIL (NOT Test) OR (Ctr > Len);
  90.  
  91.   Same := Test;
  92. END;
  93.  
  94. {.PA}
  95.  
  96. (**************************************************************************)
  97. (*                                                                        *)
  98. (*          2)   File Protection                                          *)
  99. (*                                                                        *)
  100. (*                                                                        *)
  101. (**************************************************************************)
  102.  
  103. FUNCTION ReadOnlyGetAttr(FileName : STRING) : BOOLEAN;
  104. VAR
  105.   Name      : ARRAY[1..64] OF CHAR;
  106.   DosReg    : REGISTERS;
  107.  
  108. BEGIN
  109.   S2Z(FileName,Name);
  110.   WITH DosReg DO BEGIN
  111.     DS := SEG(Name);
  112.     DX := OFS(Name);
  113.     AL := $00;    { Get Attributes }
  114.     AH := $43;
  115.     INTR(_DOS,DosReg);
  116.     IF (Flags AND $0001) = 1  { Error }
  117.       THEN ReadOnlyGetAttr := FALSE
  118.       ELSE ReadOnlyGetAttr := ((CL AND $01) = $01);
  119.     END;
  120. END;
  121.  
  122. FUNCTION ReadOnlySetAttr(FileName : STRING ; Flag : BOOLEAN) : INTEGER;
  123.  
  124. VAR
  125.   Name      : ARRAY[1..64] OF CHAR;
  126.   DosReg    : REGISTERS;
  127.  
  128. BEGIN
  129.   S2Z(FileName,Name);
  130.   WITH DosReg DO BEGIN
  131.     DS := SEG(Name);
  132.     DX := OFS(Name);
  133.     AL := $00;    { Get Attributes }
  134.     AH := $43;
  135.     INTR(_DOS,DosReg);
  136.     IF (Flags AND $0001) = 1    { Error }
  137.       THEN ReadOnlySetAttr := AX
  138.       ELSE BEGIN
  139.         IF Flag
  140.           THEN CL := CL OR  $01   { Set/Reset Read Only Bit }
  141.           ELSE CL := CL AND $FE;
  142.         DS := SEG(Name);
  143.         DX := OFS(Name);
  144.         AL := $01;    { Set Attributes }
  145.         AH := $43;
  146.         INTR(_DOS,DosReg);
  147.         IF (Flags AND $0001) = 1    { Error }
  148.           THEN ReadOnlySetAttr := AX
  149.           ELSE ReadOnlySetAttr := 0;
  150.         END;
  151.     END;
  152. END;
  153.  
  154. FUNCTION ReadOnlyExist(FileName : STRING) : BOOLEAN;
  155. VAR
  156.   AnyFDummy : FILE;
  157.   AnyF      : FILEREC ABSOLUTE AnyFDummy;
  158.   DosReg    : REGISTERS;
  159.   AXStr     : STRING;
  160.  
  161. BEGIN
  162.   ASSIGN(AnyFDummy,FileName);
  163.   WITH DosReg DO BEGIN
  164.     DS := SEG(AnyF.Name);
  165.     DX := OFS(AnyF.Name);
  166.     AL := $00;  { Read Only Access }
  167.     AH := $3D;
  168.     INTR(_DOS,DosReg);           { Open File }
  169.     IF (Flags AND $0001) = 1    { Error }
  170.       THEN BEGIN
  171.         IF AX <> 2 THEN BEGIN
  172.           STR(AX:5,AXStr);
  173.           ScrErrMsg(FileName + ' can''t be opened, DOS error: '+ AXStr);
  174.           END;
  175.         ReadOnlyExist := FALSE;
  176.         END
  177.       ELSE WITH AnyF DO BEGIN
  178.         ReadOnlyExist := TRUE;
  179.         BX := AX;
  180.         AH := $3E;
  181.         INTR(_DOS,DosReg);           { Close File }
  182.         END;
  183.     END;
  184. END;
  185.  
  186. FUNCTION FileOpen(VAR GenFileDummy;
  187.                       GenFileRecLen   : WORD;
  188.                       GenFileOpenMode : WORD) : INTEGER;
  189. VAR
  190.   GenF   : FILEREC ABSOLUTE GenFileDummy;
  191.   GenTF  : TEXTREC ABSOLUTE GenFileDummy;
  192.   DosReg : REGISTERS;
  193.  
  194. BEGIN
  195.   WITH DosReg DO BEGIN
  196.     DS := SEG(GenF.Name);
  197.     DX := OFS(GenF.Name);
  198.     AL := GenFileOpenMode;  { $00 = Read Only , $01 = Write Only, $02 = Read/Write Access }
  199.     AH := $3D;
  200.     INTR(_DOS,DosReg);           { Open File }
  201.     IF (Flags AND $0001) = 1     { Error }
  202.       THEN FileOpen := AX
  203.       ELSE WITH GenF DO BEGIN
  204.         FileOpen := 0;
  205.         Mode := FMInOut;  (*** T4 ***)
  206.         Handle := AX;
  207.         IF GenFileRecLen = 0 THEN WITH GenTF DO BEGIN  { Text File }
  208.           (* ??? Various Pointers ??? *)
  209.           ScrErrMsg('Read Only Processing Of Text Files Supported Directly by RESET');
  210.           Abend($FF,NIL);
  211.           Mode     := FMInput;
  212.           BufSize  := 128;
  213.           BufPos   := 0;
  214.           BufEnd   := 0;
  215.           END
  216.          ELSE RecSize := GenFileRecLen;
  217.         END;
  218.     END;
  219. END;
  220.  
  221. FUNCTION FileAssignAndOpen (    GenFileName      : STRING;
  222.                             VAR GenFileDummy;
  223.                                 GenFileRecLen    : WORD;
  224.                                 GenFileOpenMode  : WORD) : BOOLEAN;
  225.  
  226. VAR
  227.   GenFile : FILE ABSOLUTE GenFileDummy;
  228.  
  229. BEGIN
  230.   ASSIGN(GenFile,GenFileName);
  231.   FileAssignAndOpen := FileOpen(GenFile,GenFileRecLen,GenFileOpenMode) = 0
  232. END;
  233.  
  234. {.PA}
  235.  
  236. (**************************************************************************)
  237. (*                                                                        *)
  238. (*          3)   Text Encryption                                          *)
  239. (*                                                                        *)
  240. (*                                                                        *)
  241. (**************************************************************************)
  242.  
  243. FUNCTION EnCrypt (Orig : STRING) : STRING;
  244.  
  245. VAR
  246.   Ctr : INTEGER;
  247.   Len : INTEGER;
  248.  
  249. BEGIN
  250.   Len := LENGTH(Orig);
  251.   FOR Ctr := 1 TO Len DO BEGIN
  252.     IF Odd(Ctr)
  253.       THEN Orig[Ctr] := CHR(ORD(Orig[Ctr]) + (Len-Ctr+1))
  254.       ELSE Orig[Ctr] := CHR(ORD(Orig[Ctr]) - (Len-Ctr+1));
  255.     IF NOT (Orig[Ctr] IN ['!'..'~']) THEN BEGIN
  256.         EnCrypt := '';
  257.         EXIT;
  258.         END;
  259.     END;
  260.   EnCrypt := Orig;
  261. END;
  262.  
  263. FUNCTION DeCrypt (Orig : STRING) : STRING;
  264.  
  265. VAR
  266.   Ctr : INTEGER;
  267.   Len : INTEGER;
  268.  
  269. BEGIN
  270.   Len := LENGTH(Orig);
  271.   FOR Ctr := 1 TO LENGTH(Orig) DO
  272.     IF Odd(Ctr)
  273.       THEN Orig[Ctr] := CHR(ORD(Orig[Ctr]) - (Len-Ctr+1))
  274.       ELSE Orig[Ctr] := CHR(ORD(Orig[Ctr]) + (Len-Ctr+1));
  275.   DeCrypt := Orig;
  276. END;
  277.  
  278. {.PA}
  279.  
  280. (**************************************************************************)
  281. (*                                                                        *)
  282. (*          4)   General Purpose Video                                    *)
  283. (*                                                                        *)
  284. (**************************************************************************)
  285.  
  286. PROCEDURE GenBeep (Frequency, Duration : WORD);
  287. BEGIN
  288.   IF Frequency < 25 THEN Frequency := 460;
  289.   IF Duration  < 5  THEN Duration  := 30;
  290.   SOUND (Frequency);
  291.   DELAY (Duration);
  292.   NOSOUND;
  293.   DELAY (10);  {Allow the sound to stop before leaving this procedure}
  294. END;
  295.  
  296. FUNCTION ColorMonitorInstalled : BOOLEAN;
  297. (* This will NOT work for Hercules card unless GrafBase is $B000 *)
  298. CONST
  299.   GrafBase = $B800;
  300.  
  301. VAR
  302.   I      : INTEGER;
  303.   DosReg : REGISTERS;
  304.  
  305. BEGIN
  306.   INTR ($11,DosReg);
  307.   I := MEMW [GrafBase:0000];
  308.   MEMW [GrafBase:0000] := NOT I;
  309.   ColorMonitorInstalled :=
  310.     (I = NOT MEMW [GrafBase:0000]) AND (DosReg.AX AND $30 <> $30);
  311.   MEMW [GrafBase:0000] := I;
  312. END;
  313.  
  314. PROCEDURE Cursor (Visible : BOOLEAN);
  315. VAR
  316.   DosReg : REGISTERS;
  317.  
  318. BEGIN
  319.   WITH DosReg DO BEGIN                  { First return the scan lines.   }
  320.     AX := $0300;                        { BIOS VIDEO subfunction 3       }
  321.     BX := $0000;                        { Only works for display page 0  }
  322.     INTR (_VIDEO, DosReg);
  323.     IF NOT Visible THEN                 { Turn cursor off by setting     }
  324.       CX := CX OR $3000                 { bits 5 and 6 of CH, and        }
  325.     ELSE                                { turn curson on by clearing the }
  326.       CX := CX AND $CFFF;               { bits.                          }
  327.     AX := $0100;                        { Write the scan lines back out. }
  328.     INTR (_VIDEO, DosReg)
  329.     END;
  330. END;
  331.  
  332. PROCEDURE CursorInsertSize;
  333. VAR
  334.   DosReg : REGISTERS;
  335.  
  336. BEGIN
  337.   WITH DosReg DO BEGIN
  338.     AX := $0300;
  339.     BX := $0000;
  340.     INTR (_VIDEO, DosReg);
  341.  
  342.     IF CL = 7 THEN CH := (CH AND $30) OR $04
  343.               ELSE CH := (CH AND $30) OR $0A;
  344.     AX := $0100;
  345.     INTR (_VIDEO, DosReg);
  346.     END;
  347. END;
  348.  
  349. PROCEDURE CursorOverwriteSize;
  350. VAR
  351.   DosReg : REGISTERS;
  352.  
  353. BEGIN
  354.   WITH DosReg DO BEGIN
  355.     AX := $0300;
  356.     BX := $0000;
  357.     INTR (_VIDEO, DosReg);
  358.  
  359.     IF CL = 7 THEN CH := (CH AND $30) OR $06
  360.               ELSE CH := (CH AND $30) OR $0C;
  361.     AX := $0100;
  362.     INTR (_VIDEO, DosReg);
  363.     END;
  364. END;
  365.  
  366. FUNCTION ScrForeCursorColor : WORD;
  367. VAR
  368.    Reg : REGISTERS;
  369.  
  370. BEGIN
  371.    Reg.AH := $08;
  372.    Reg.BH := $00;
  373.    INTR ($10, Reg);
  374.    ScrForeCursorColor := (Reg.AH AND $0F);
  375. END;
  376.  
  377. FUNCTION ScrBackCursorColor : WORD;
  378. VAR
  379.    Reg : REGISTERS;
  380.  
  381. BEGIN
  382.    Reg.AH := $08;
  383.    Reg.BH := $00;
  384.    INTR ($10, Reg);
  385.    ScrBackCursorColor := ((Reg.AH AND $70) SHR 4);
  386. END;
  387.  
  388. {.PA}
  389.  
  390. (**************************************************************************)
  391. (*                                                                        *)
  392. (*          5)   Video Messages                                           *)
  393. (*                                                                        *)
  394. (*                                                                        *)
  395. (**************************************************************************)
  396.  
  397. PROCEDURE Wait (DispWait : BOOLEAN);
  398. TYPE
  399.   T_Wait = ARRAY [1..4] OF WORD;
  400.  
  401. CONST
  402.  
  403.   WaitOn        : BOOLEAN = FALSE;
  404.   WaitMsg       : T_Wait = ($8257, $8241, $8249, $8254);  { WAIT green on black }
  405.   SaveColorWait : T_Wait = (0,0,0,0);
  406.   SaveMonoWait  : T_Wait = (0,0,0,0);
  407.  
  408. VAR
  409.   ColorWait     : T_Wait ABSOLUTE $B800:$0F98;
  410.   MonoWait      : T_Wait ABSOLUTE $B000:$0F98;
  411.  
  412. BEGIN
  413.   IF (DispWait) AND (NOT WaitOn) THEN BEGIN
  414.     SaveColorWait := ColorWait;
  415.     SaveMonoWait  := MonoWait;
  416.     ColorWait     := WaitMsg;
  417.     MonoWait      := WaitMsg;
  418.     WaitOn        := TRUE;
  419.     END
  420.   ELSE IF (NOT DispWait) AND (WaitOn) THEN BEGIN
  421.     WaitOn    := FALSE;
  422.     ColorWait := SaveColorWait;
  423.     MonoWait  := SaveMonoWait;
  424.     END;
  425. END;
  426.  
  427. PROCEDURE Pause;
  428. VAR
  429.   SaveColorDot : INTEGER;
  430.   SaveMonoDot  : INTEGER;
  431.   ColorScrDot  : WORD ABSOLUTE $B800:$0F00;
  432.   MonoScrDot   : WORD ABSOLUTE $B000:$0F00;
  433.   CH           : CHAR;
  434.  
  435. BEGIN
  436.   SaveColorDot := ColorScrDot;
  437.   SaveMonoDot  := MonoScrDot;
  438.  
  439.   ColorScrDot := $8F1D; {Display a nice character to flash on the screen}
  440.   MonoScrDot  := $8F1D;
  441.   REPEAT
  442.     UNTIL KEYPRESSED;
  443.   CH := READKEY;
  444.  
  445.   ColorScrDot := SaveColorDot;
  446.   MonoScrDot  := SaveMonoDot;
  447. END;
  448.  
  449. PROCEDURE ScrStatMsg (Message : STRING);
  450. VAR
  451.    X, Y, Color : INTEGER;
  452.    BackColor   : INTEGER;
  453.  
  454. BEGIN
  455.   Color := ScrForeCursorColor;
  456.   BackColor := ScrBackCursorColor;
  457.   IF Message <> '' THEN BEGIN
  458.     IF NOT ColorMonitorInstalled
  459.       THEN TEXTCOLOR(D_ForeColor)
  460.       ELSE TEXTCOLOR(D_StatColor);
  461.     TEXTBACKGROUND(D_SurroundColor);
  462.     END;
  463.   X := WhereX;
  464.   Y := WhereY;
  465.   GOTOXY (1,25);
  466.   WRITE(LJS(Message,76));
  467.   TEXTCOLOR(Color);
  468.   TEXTBACKGROUND(BackColor);
  469.   GOTOXY(X,Y);
  470. END;
  471.  
  472. PROCEDURE ScrErrMsg (Message : STRING );
  473.  
  474. VAR
  475.    X, Y, Color : INTEGER;
  476.    BackColor   : INTEGER;
  477.    Ctr         : INTEGER;
  478.  
  479. BEGIN
  480.   Color := ScrForeCursorColor;
  481.   BackColor := ScrBackCursorColor;
  482.   IF NOT ColorMonitorInstalled
  483.     THEN TEXTCOLOR(D_ForeColor)
  484.     ELSE TEXTCOLOR(D_ErrColor);
  485.   TEXTBACKGROUND(D_SurroundColor);
  486.   X := WhereX;
  487.   Y := WhereY;
  488.   GOTOXY (1,25);
  489.   Message := LJS(Message,64);
  490.   Message := Message + ' Press '+#17#217+'   ';
  491.   WRITE(Message);
  492.   IF NOT KbdScrollLockStatus THEN GenBeep (0,0);
  493.   REPEAT
  494.     UNTIL KbdInputValue = K_Enter;
  495.   GOTOXY (1,25);
  496.   TEXTCOLOR(Color);
  497.   TEXTBACKGROUND(BackColor);
  498.   Message := LJS(' ',76);
  499.   WRITE(Message);    { Remove message from screen }
  500.   GOTOXY(X,Y);
  501. END;
  502.  
  503. FUNCTION ScrYouAreSure (Message : STRING ) : BOOLEAN;
  504. BEGIN
  505.   IF Message = '' THEN Message := 'CONTINUE';
  506.   Message := Message + ',';
  507.   Message := LJS(Message,36);
  508.   ScrStatMsg ('Hit any key to '+Message+'  or hit <ESC> to CANCEL.');
  509.   IF KbdInputValue = K_Esc THEN ScrYouAreSure := FALSE
  510.                            ELSE ScrYouAreSure := TRUE;
  511.   ScrStatMsg('');
  512. END;
  513.  
  514. FUNCTION ScrYN (Message : STRING) : BOOLEAN;
  515. VAR
  516.   X,Y,Color : INTEGER;
  517.   BackColor : INTEGER;
  518.  
  519. BEGIN
  520.   IF Message = '' THEN Message := 'Are You Sure';
  521.   Message := LJS(Message,66);
  522.   X := WHEREX;
  523.   Y := WHEREY;
  524.   Color := ScrForeCursorColor;
  525.   BackColor := ScrBackCursorColor;
  526.   ScrStatMsg(Message + ' (Y/N)? ');
  527.   IF NOT ColorMonitorInstalled
  528.     THEN TEXTCOLOR(D_ForeColor)
  529.     ELSE TEXTCOLOR(D_StatColor);
  530.   TEXTBACKGROUND(D_SurroundColor);
  531.   GOTOXY(76,25);
  532.   REPEAT
  533.     UNTIL CHR(KbdInputValue) IN ['Y', 'y', 'N', 'n'];
  534.   WRITE (KbdLastChar);
  535.   CASE KbdLastChar OF
  536.     'Y', 'y' : ScrYN := TRUE;
  537.     'N', 'n' : ScrYN := FALSE;
  538.     END; {CASE}
  539.   GOTOXY (X,Y);
  540.   TEXTCOLOR(Color);
  541.   TEXTBACKGROUND(BackColor);
  542.   ScrStatmsg('');
  543. END;
  544.  
  545. {.PA}
  546.  
  547. (**************************************************************************)
  548. (*                                                                        *)
  549. (*          6)   Disk and Memory Sizes                                    *)
  550. (*                                                                        *)
  551. (*                                                                        *)
  552. (**************************************************************************)
  553.  
  554. FUNCTION BytesOnDiskFree(Drive : CHAR) : LONGINT;
  555. VAR
  556.   DosReg    : REGISTERS;
  557.  
  558. BEGIN
  559.   Drive := UPCASE(Drive);
  560.   IF NOT (Drive IN [' ','A'..'Z']) THEN BEGIN
  561.     BytesOnDiskFree := -1;
  562.     EXIT;
  563.     END;
  564.   WITH DosReg DO BEGIN
  565.     IF Drive = ' '
  566.       THEN DL := 0
  567.       ELSE DL := ORD(Drive) - ORD('@');
  568.     AH := $36;
  569.     INTR(_DOS,DosReg);
  570.     IF AX = $FFFF
  571.       THEN BytesOnDiskFree := -1
  572.       ELSE BytesOnDiskFree := LONGINT(CX) * AX * BX;
  573.     END;
  574. END;
  575.  
  576. FUNCTION FreeDOSMem : LONGINT;
  577. VAR
  578.   DosReg : REGISTERS;
  579.  
  580. BEGIN
  581.   WITH DosReg DO BEGIN
  582.     AH := $48;
  583.     BX := $FFFF;
  584.     INTR($21,DosReg);
  585.     FreeDOSMem := LONGINT(BX) * 16;
  586.     END;
  587. END;
  588.  
  589. FUNCTION SizeOfMem : LONGINT;
  590. VAR
  591.   DosReg : REGISTERS;
  592.  
  593. BEGIN
  594.   WITH DosReg DO BEGIN
  595.     INTR ($12, DosReg);
  596.     SizeOFMem := LONGINT(AX) * 1024;
  597.     END;
  598. END;
  599.  
  600. FUNCTION StackAvail : WORD;
  601.  
  602. VAR
  603.   SOfs : WORD;
  604.  
  605. BEGIN
  606. (*                           { OVERKILL BUT 'Neat' }
  607.   INLINE($36/$89/$66/<SOfs); { MOV SS:SOfs,SP --> MOV SS:[BP-OFS(SOfs),SP],SP }
  608.   StackAvail := SOfs+2;
  609. *)
  610.   StackAvail := OFS(SOfs)+2;
  611. END;
  612.  
  613. {.PA}
  614.  
  615. (**************************************************************************)
  616. (*                                                                        *)
  617. (*          7)   Instruction Timing                                       *)
  618. (*                                                                        *)
  619. (*                                                                        *)
  620. (**************************************************************************)
  621.  
  622. FUNCTION TimeElapsed : REAL;
  623.  
  624. VAR
  625.   Reg : REGISTERS;
  626.  
  627. BEGIN
  628.   Reg.AH := $2C;
  629.   INTR($21,Reg);
  630.   WITH Reg DO
  631.     TimeElapsed :=  CH*3600.0 + CL*60.0 + DH + DL/100.0;
  632. END;
  633.  
  634. FUNCTION TimeTotal(Start , Stop : REAL) : STRING;
  635.  
  636. BEGIN
  637.   TimeTotal := Strip(R2S((Stop - Start),'###,###@.@#'),S_Leading);
  638. END;
  639.  
  640.  
  641. {.PA}
  642.  
  643. (**************************************************************************)
  644. (*                                                                        *)
  645. (*          8)   General Purpose File                                     *)
  646. (*                                                                        *)
  647. (*                                                                        *)
  648. (**************************************************************************)
  649.  
  650. FUNCTION Exist (FileName: STRING) : BOOLEAN;
  651. VAR
  652.    Fil : FILE;
  653. BEGIN
  654.    ASSIGN (Fil, FileName);
  655.    (*$I-*)
  656.    RESET (Fil);
  657.    (*$I+*)
  658.    IF (IORESULT = 0) THEN BEGIN
  659.       CLOSE (Fil);
  660.       Exist := TRUE;
  661.       END
  662.    ELSE Exist := FALSE;
  663. END;
  664.  
  665. FUNCTION LinesInFile (FileName : STRING) : INTEGER;
  666. VAR
  667.   Ctr      : INTEGER;
  668.   TempFile : TEXT;
  669.  
  670. BEGIN
  671.   IF ReadOnlyExist (FileName) THEN BEGIN
  672.     ASSIGN (TempFile, FileName);
  673.     RESET  (TempFile);
  674.     Ctr := 0;
  675.     WHILE NOT EOF (TempFile) DO BEGIN
  676.       Ctr := SUCC (Ctr);
  677.       READLN (TempFile);
  678.       END;
  679.     LinesInFile := Ctr;
  680.     CLOSE (TempFile);
  681.     END
  682.   ELSE
  683.     LinesInFile := -1;
  684. END;
  685.  
  686. FUNCTION GetFileDateAndTimeString (FileName : STRING) : STRING;
  687. VAR
  688.    Day, Month, Year,
  689.    Hour, Minute, Second : INTEGER;
  690.    AmPm                 : STRING[3];
  691.    DosReg               : REGISTERS;
  692.  
  693. BEGIN
  694.    FileName := FileName + #0;
  695.    WITH DosReg DO BEGIN
  696.       DS := SSeg;                { FileName is a Stack variable }
  697.       DX := OFS (FileName) + 1;  { ASCIIZ String }
  698.       AX := $3D00;               { Open a File }
  699.       INTR (_DOS, DosReg);
  700.       IF (FLAGS AND $0001) = 1 THEN BEGIN
  701.          GetFileDateAndTimeString := 'FileError # '+ I2S(AX,'###')+' on '+FileName;
  702.          EXIT;
  703.          END;
  704.       BX := AX;
  705.       AX := $5700;               { Get date and time }
  706.       INTR (_DOS, DosReg);
  707.       Month  := (DX SHR 5)  AND $000F;
  708.       Day    :=  DX         AND $001F;
  709.       Year   := (DX SHR 9)  AND $007F + 1980;
  710.       Hour   := (CX SHR 11) AND $001F;
  711.       Minute := (CX SHR 5)  AND $003F;
  712.       Second :=  CX         AND $001F * 2;
  713.       IF Hour >= 12 THEN
  714.          AmPm := ' pm'
  715.       ELSE
  716.          AmPm := ' am';
  717.       IF Hour > 12 THEN
  718.          Hour := Hour - 12;
  719.       GetFileDateAndTimeString
  720.                          := I2S (Month, '@@')   + '/' +
  721.                             I2S (Day,   '@@')   + '/' +
  722.                             I2S (Year,  '@@@@') + ' ' +
  723.                             I2S (Hour,  '@@')   + ':' +
  724.                             I2S (Minute, '@@')  + AmPm;
  725.       AX := $3E00;    { Close File }
  726.       INTR (_DOS, DosReg);
  727.       END;
  728. END;
  729.  
  730. FUNCTION GetFileDateAndTimeLongInt (FileName : STRING) : LONGINT;
  731. VAR
  732.   DosReg : REGISTERS;
  733.  
  734. BEGIN
  735.    FileName := FileName + #0;
  736.    WITH DosReg DO BEGIN
  737.       DS := SSEG;                { FileName is a Stack variable }
  738.       DX := OFS (FileName) + 1;  { ASCIIZ String }
  739.       AX := $3D00;               { Open a File }
  740.       INTR (_DOS, DosReg);
  741.       IF (FLAGS AND $0001) = 1 THEN BEGIN
  742.          GetFileDateAndTimeLongInt := -1;
  743.          EXIT;
  744.          END;
  745.       BX := AX;
  746.       AX := $5700;               { Get date and time }
  747.       INTR (_DOS, DosReg);
  748.       GetFileDateAndTimeLongInt := LONGINT(DX) SHL 16 + CX;
  749.       AX := $3E00;    { Close File }
  750.       INTR (_DOS, DosReg);
  751.       END;
  752. END;
  753.  
  754. {.PA}
  755.  
  756. (**************************************************************************)
  757. (*                                                                        *)
  758. (*          9)   Math                                                     *)
  759. (*                                                                        *)
  760. (*                                                                        *)
  761. (**************************************************************************)
  762.  
  763. FUNCTION Power (X, Y : REAL) : REAL;
  764. BEGIN
  765.    Power := EXP (Y * LN (X));
  766. END;
  767.  
  768. FUNCTION Log (x : REAL) : REAL;
  769. BEGIN
  770.    Log := (Ln (x)/ Ln (10));
  771. END;
  772.  
  773. {.PA}
  774.  
  775. (**************************************************************************)
  776. (*                                                                        *)
  777. (*          10)  DOS and Environment                                      *)
  778. (*                                                                        *)
  779. (*                                                                        *)
  780. (**************************************************************************)
  781.  
  782. FUNCTION DOSVersionR : REAL;
  783. VAR
  784.   DosReg : REGISTERS;
  785.  
  786. BEGIN
  787.   WITH DosReg DO BEGIN
  788.     AH := $30;
  789.     INTR (_DOS, DosReg);
  790.     IF AL = 0 THEN DOSVersionR := 1.1 {All the info we can get for DOS 1.x}
  791.               ELSE DOSVersionR := AL + (AH / 100.0);
  792.     END;
  793. END;
  794.  
  795. FUNCTION WhoAmI : STRING;
  796. VAR
  797.   E : INTEGER;   { environment segment }
  798.   I : INTEGER;   { offset within segment }
  799.   T : STRING;    { Temp Program name }
  800.  
  801. BEGIN
  802.   WhoAmI := '';
  803.   T      := '';
  804.   IF DosVersion < 3.0 THEN EXIT;
  805.   E := MEMW[PREFIXSEG:$2C];          { get environment segment }
  806.   I := 0;                            { start at the beginning  }
  807.   REPEAT
  808.     WHILE MEM[E:I] <> 0 DO           { search a zero byte }
  809.       I := I+1;
  810.     I := I+1;
  811.     UNTIL MEM[E:I] = 0;              { stop at second zero byte }
  812.   I := I+3;                          { skip to loaded file name }
  813.   WHILE (MEM[E:I] <> 0) DO BEGIN     { display the load descriptor }
  814.     T := T + (CHR(MEM[E:I]));
  815.     I := I+1;
  816.     END;
  817.   WhoAmI := T;
  818. END;
  819.  
  820. FUNCTION GetEnvString(EnvVar : STRING) : STRING;
  821. VAR
  822.   E    : INTEGER;   { environment segment }
  823.   I    : INTEGER;   { offset within segment }
  824.   T    : STRING;    { environment value }
  825.   Sep  : INTEGER;   { position of = }
  826.   Pre  : STRING;    { value before = }
  827.   Post : STRING;    { value after = }
  828.   Done : BOOLEAN;   { found variable in question }
  829.  
  830. BEGIN
  831.   EnvVar := Strip(StrCase(EnvVar,S_ToUpper),S_AllSpaces);
  832.   IF EnvVar = '' THEN BEGIN
  833.     GetEnvString := '';       { why bother searching for nothing }
  834.     EXIT;
  835.     END;
  836.   IF EnvVar[LENGTH(EnvVar)] = '=' THEN EnvVar := COPY(EnvVar,1,LENGTH(EnvVar)-1);
  837.   GetEnvString := '';
  838.   E := MEMW[PREFIXSEG:$2C];          { get environment segment }
  839.   I := 0;                            { start at the beginning  }
  840.   Done := FALSE;
  841.   REPEAT
  842.     T := '';
  843.     WHILE MEM[E:I] <> 0 DO BEGIN     { search a zero byte }
  844.       T := T + (CHR(MEM[E:I]));
  845.       I := I+1;
  846.       END;
  847.     Sep := POS('=',T);
  848.     IF Sep <> 0 THEN BEGIN
  849.       Pre  := Strip(StrCase(COPY(T,1,Sep-1)        ,S_ToUpper),S_AllSpaces);
  850.       Post := Strip(StrCase(COPY(T,Sep+1,LENGTH(T)),S_ToUpper),S_Leading+S_Trailing);
  851.       IF Pre = EnvVar THEN Done := TRUE;
  852.       END;
  853.     I := I+1;
  854.     UNTIL (MEM[E:I] = 0) OR Done;    { stop at second zero byte }
  855.   IF Done
  856.     THEN GetEnvString := Post
  857.     ELSE GetEnvString := '';
  858. END;
  859.  
  860. FUNCTION GetDMLVersion(Module : WORD) : STRING;
  861. BEGIN
  862.   IF Module > 4 THEN Module := 0;
  863.   GetDMLVersion := R2S(Versions[Module],'##.@@');
  864. END;
  865.  
  866. FUNCTION GetDMLVersions : STRING;
  867. BEGIN
  868.   GetDMLVersions := 'Unit Versions: ' +
  869.                'DML: '  + GetDMLVersion(0) +
  870.              ', GEN: '  + GetDMLVersion(1) +
  871.              ', NUM: '  + GetDMLVersion(2) +
  872.              ', STRG: ' + GetDMLVersion(3) +
  873.              ', KBD: '  + GetDMLVersion(4);
  874. END;
  875.